home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_129 / patch / ver2.0 / filereq.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  23KB  |  982 lines

  1.  
  2. /*
  3.  *  STDFILE -- Standard File Requestor. Version 2.0a 15 June 1987
  4.  *
  5.  *  AUTHOR -- Peter da Silva      US (713) 497-4372
  6.  *
  7.  *  Reorganized by Matthew Dillon for use with * and ?.  Added:
  8.  *    -device name in File string gadget transfered to directory
  9.  *     gadget without closing the window.
  10.  *    -bug when requesting volume ""... current directory lock would
  11.  *     get unlocked!
  12.  *    -additional intuitive features added
  13.  *    -coding reorganized
  14.  *
  15.  *    Copyright (c) 1987 Peter da Silva, all rights reserved.
  16.  *    Changes (c)Copyright 1987 Matthew Dillon, all rights reserved.
  17.  *
  18.  *    This module may be freely used in any product, commercial or
  19.  *    otherwise, provided credit is given for this module and
  20.  *    and provided this notice remains intact in the source. The
  21.  *    intent of this module is to provide a standard file requestor
  22.  *    such as is available on the Macintosh, in GEM on the IBM-PC
  23.  *    and Atari ST, and in the Microsoft Windows software on the
  24.  *    IBM-PC. The advantage this module has over other requestors
  25.  *    is that it minimises disk accesses: an important consideration
  26.  *    given the structure of AmigaDos directories. If you need to
  27.  *    modify it for your needs, by all means go ahead... but please
  28.  *    conform to the intent of this program as stated above. If you
  29.  *    have suggestions for improvements, by all means call me at
  30.  *    the number listed above.
  31.  *
  32.  * Enhancements in the current version:
  33.  *
  34.  *    Gadgets now boxed. Display generally cleaned up.
  35.  *
  36.  *    True "dictionary order" for searches.
  37.  *
  38.  *    Default pattern can now be specified. Default file name now
  39.  *    specified in a single argument.
  40.  *
  41.  *    Directories always match.
  42.  *
  43.  *    Null pattern converted to "#?" universal wildcard.
  44.  *
  45.  *    If you attempt to build a file name longer than 128 characters the
  46.  *    screen will flash and the operation will be aborted.
  47.  *
  48.  *    "Volumes" gadget, using the device list code in "mounted". This
  49.  *    gadget brings up a list of all currently mounted volumes for
  50.  *    selection. Volumes leaves the directory specification intact, so
  51.  *    you can quickly return to where you left off.
  52.  *
  53.  *    With these enhancements it is now possible to select any file on
  54.  *    any device without touching the keyboard. This is now release 2.0,
  55.  *    as it is significantly better than 1.0.
  56.  *
  57.  * Acknowledgements:
  58.  *
  59.  *    Thanks to Jeff Lydiatt for the pattern matching code in PatMatch.c
  60.  *    Thanks to Jay Miner, =RJ= and the whole Amiga team for the Amiga
  61.  *    itself.
  62.  *
  63.  * Environment:
  64.  *
  65.  *    IntuitionBase and GfxBase must be open. dos.library must be open
  66.  *    under the name "DosLibrary". Link with PatMatch.o and VolList.o.
  67.  *
  68.  * Usage:
  69.  *
  70.  *    #define MAXFILENAME 128
  71.  *
  72.  *    int stdfile(title, default_file, default_pat, name);
  73.  *    char *title;
  74.  *    char *default_file;
  75.  *    char *default_pattern;
  76.  *    char name[MAXFILENAME];
  77.  *
  78.  *    +-----------------------------------+
  79.  *    |o| Title ------------------- |  |  | title parameter, or "File Name"
  80.  *    |-----------------------------------|
  81.  *    | Directory: [              ] | Directory parameter, or current.
  82.  *    | File name: [              ] | Default parameter, or empty.
  83.  *    | Pattern:   [              ] | Initially empty, if the user
  84.  *    | +-------------------------------+ | enters anything here it will
  85.  *    | | [Filename]               |  | | be used to select files. The
  86.  *    | | [Filename]               |  | | file display will also be empty
  87.  *    | | [Filename]               |@@| | to start with to avoid excess
  88.  *    | | [Filename]               |@@| | disk I/O. If the user selects
  89.  *    | |                   |@@| | here the directory will be
  90.  *    | |                   |@@| | scanned looking for files
  91.  *    | |                   |  | | matching the specified pattern,
  92.  *    | |                   |  | | or "*" if no pattern is given.
  93.  *    | |                   |  | |
  94.  *    | +-------------------------------+ | ACCEPT returns 1. CANCEL
  95.  *    | [ACCEPT]    [VOLUMES]    [CANCEL] | or the close gadget return 0.
  96.  *    +-----------------------------------+ VOLUMES displays volume names.
  97.  *
  98.  *    The number of filenames displayed is specified at compile time in the
  99.  *    constant MAXFILES. The maximum size of a filename is specified in the
  100.  *    constant MAXNAME. The parameter "Default file" will be broken into
  101.  *    directory and file parts.
  102.  */
  103.  
  104. char *Copyright =
  105. "stdfile V2.0a. Copyright (c) 1987 Peter da Silva. All rights reserved.";
  106.  
  107. #include <intuition/intuitionbase.h>
  108. #include <intuition/intuition.h>
  109. #include <libraries/dos.h>
  110. #include <libraries/dosextens.h>
  111. #include <exec/memory.h>
  112.  
  113. typedef unsigned char  ubyte;
  114. typedef unsigned short uword;
  115. typedef unsigned long  ulong;
  116. typedef struct FileInfoBlock FIB;
  117. typedef struct DeviceList    DEVLIST;
  118. typedef struct DosLibrary    DOSLIB;
  119. typedef struct DosInfo         DOSINFO;
  120. typedef struct RootNode      ROOTNODE;
  121. typedef struct IntuiMessage  IMESS;
  122.  
  123. extern void CalcPropGadget();
  124. extern void ProcessFileName();
  125.  
  126. extern void *malloc();
  127. extern void *GetMsg();
  128. extern struct Window *OpenWindow();
  129.  
  130. #define MAXFILES 8
  131. #define MAXNAME 32
  132. #define MAXFULL (MAXNAME*4)
  133.  
  134. /* SIZING PARAMS */
  135.  
  136. #define Z        NULL
  137. #define INDENT        6
  138. #define LEFTMAR     (INDENT-1)
  139. #define BORDER        3
  140. #define CHSIZ        8
  141. #define HT        CHSIZ
  142. #define BASELINE    6
  143.  
  144. /* GADGET BORDERS */
  145.  
  146. #define IN1        LEFTMAR+10*CHSIZ
  147. #define IN3        LEFTMAR+3
  148. #define IN4        -(INDENT+6*CHSIZ+1)
  149. #define IN5        -(INDENT+CHSIZ*2)
  150. #define IN6        ((WINWD-WD6)/2)
  151. #define WD1        -(INDENT+IN1)
  152. #define WD3        (6*CHSIZ)
  153. #define WD4        (6*CHSIZ)
  154. #define WD5        (CHSIZ*2+2)
  155. #define WD6        (7*CHSIZ)
  156. #define TP1        (CHSIZ+BORDER)
  157. #define TP2        (TP1+HT+1)
  158. #define TP3        (TP2+HT+1)
  159. #define TP4        -(BORDER+HT4-1)
  160. #define TP5        (TP3+HT+BORDER)
  161. #define HT4        (HT+1)
  162. #define HT5        CHSIZ*MAXFILES+INDENT
  163.  
  164. #define WINHT        (TP5 + HT5 + (-TP4) + BORDER)
  165. #define WINWD        (INDENT*4 + (MAXNAME+2)*CHSIZ)
  166. #define WININ        (640-WINWD)/2
  167. #define WINTP        (200-WINHT)/2
  168.  
  169. #define HOMEX        (INDENT+LEFTMAR)
  170. #define HOMEY        (TP5+BORDER)
  171. #define LASTX        (HOMEX+MAXNAME*CHSIZ)
  172. #define LASTY        (HOMEY+MAXFILES*CHSIZ)
  173.  
  174. #define BTP        TP5
  175. #define BIN        LEFTMAR
  176. #define BWD        (WINWD-INDENT-BIN)
  177. #define BHT        (WINHT-BTP-(-TP4+BORDER+1))
  178.  
  179. #define SF        GADGHCOMP|GRELWIDTH
  180. #define SEL        SELECTED
  181. #define BF1        GADGHCOMP|GRELBOTTOM
  182. #define BF2        GADGHCOMP|GRELBOTTOM|GRELRIGHT
  183. #define PF        GRELRIGHT
  184.  
  185. #define SA        RELVERIFY
  186. #define CEN        STRINGCENTER
  187. #define BA        RELVERIFY
  188. #define PA        RELVERIFY
  189.  
  190. #define SI(n)      (APTR)&STD_String[n]
  191. #define G(n)       &STD_Gadget[n]
  192. #define IMAG       (APTR)&STD_Image
  193. #define PROP       (APTR)&STD_Prop
  194.  
  195. #define SG       STRGADGET
  196. #define BG       BOOLGADGET
  197. #define PG       PROPGADGET
  198.  
  199. #define FP       AUTOBACKPEN
  200. #define BP       AUTOFRONTPEN
  201.  
  202. #define OKTEXT       &STD_OK
  203. #define NOTEXT       &STD_CANCEL
  204. #define VLTEXT       &STD_VOLUME
  205.  
  206. static int DoneFlag;
  207.  
  208. #define DirName    SBuffer[0]
  209. #define FileName   SBuffer[1]
  210. #define PatName    SBuffer[2]
  211. #define STRINGS    3
  212.  
  213. static UBYTE SBuffer[STRINGS][MAXFULL];
  214. static UBYTE Undo[MAXFULL];
  215.  
  216. static struct StringInfo STD_String[STRINGS] = {
  217.     {SBuffer[0],Undo,0,MAXFULL,0},
  218.     {SBuffer[1],Undo,0,MAXFULL,0},
  219.     {SBuffer[2],Undo,0,MAXFULL,0}
  220. };
  221.  
  222. static struct PropInfo STD_Prop = { AUTOKNOB|FREEVERT, 0, 0, 0, 0 };
  223.  
  224. static struct IntuiText STD_OK =
  225.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"ACCEPT", Z };
  226. static struct IntuiText STD_CANCEL =
  227.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"CANCEL", Z };
  228. static struct IntuiText STD_VOLUME =
  229.     { FP, BP, JAM2, 0, 1, Z, (UBYTE *)"VOLUMES", Z };
  230.  
  231. #define BUTTONS 3
  232. #define BUTVEC 8
  233.  
  234. static SHORT butvecs[BUTTONS][BUTVEC*2] = {
  235.     {-2,HT4,-2,-1, WD3+1,-1, WD3+1,HT4, -3, HT4, -3,-1, WD3+2,-1, WD3+2, HT4 },
  236.     {-2,HT4,-2,-1, WD4+1,-1, WD4+1,HT4, -3, HT4, -3,-1, WD4+2,-1, WD4+2, HT4 },
  237.     {-2,HT4,-2,-1, WD6+1,-1, WD6+1,HT4, -3, HT4, -3,-1, WD6+2,-1, WD6+2, HT4 }
  238. };
  239.  
  240. static struct Border ButBorder[BUTTONS] = {
  241.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[0], NULL},
  242.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[1], NULL},
  243.     {0, 0, FP, BP, JAM1, BUTVEC, butvecs[2], NULL}
  244. };
  245.  
  246. #define BB(n) (APTR)&ButBorder[n]
  247.  
  248. static struct Image STD_Image;
  249.  
  250. #define DIRID 0
  251. #define FILID 1
  252. #define PATID 2
  253. #define YESID 3
  254. #define CANID 4
  255. #define VOLID 5
  256. #define BARID 6
  257. #define GADGETS 7
  258.  
  259. static struct Gadget STD_Gadget[GADGETS] = {
  260.     /*NEXT, LFT, TP,WDTH, H, FLAG,  ACT, TYP, REND, Z, TXT, Z, SPEC, ID, Z */
  261.     { G(1), IN1,TP1, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(0), 0, 0 },
  262.     { G(2), IN1,TP2, WD1,HT, SF|SEL, SA,  SG,    Z, Z,   Z, Z, SI(1), 1, 0 },
  263.     { G(3), IN1,TP3, WD1,HT, SF,     SA,  SG,    Z, Z,   Z, Z, SI(2), 2, 0 },
  264.     { G(4), IN3,TP4, WD3,HT4,BF1,    BA,  BG,BB(0), Z, OKTEXT, Z,  Z, 3, 0 },
  265.     { G(5), IN4,TP4, WD4,HT4,BF2,    BA,  BG,BB(1), Z, NOTEXT, Z,  Z, 4, 0 },
  266.     { G(6), IN6,TP4, WD6,HT4,BF1,    BA,  BG,BB(2), Z, VLTEXT, Z,  Z, 5, 0 },
  267.     { NULL, IN5,TP5, WD5,HT5,PF,     PA,  PG, IMAG, Z,     Z, Z,    PROP, 6, 0 }
  268. };
  269.  
  270. static struct NewWindow STD_NewWindow = {
  271.     WININ, WINTP, WINWD, WINHT, -1, -1,
  272.     REFRESHWINDOW|MOUSEBUTTONS|GADGETUP|CLOSEWINDOW,
  273.     WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|ACTIVATE,
  274.     G(0), NULL, (ubyte *)"File Name Requestor",
  275.     NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
  276. };
  277.  
  278. static struct Window *STD_Window;
  279.  
  280. #define NVEC 6
  281.  
  282. static SHORT Vectors[NVEC*2] = {
  283.     BIN+1, BTP,
  284.     BIN+1, BTP+BHT,
  285.     BIN+BWD, BTP+BHT,
  286.     BIN+BWD, BTP,
  287.     BIN, BTP,
  288.     BIN, BTP+BHT
  289. };
  290.  
  291. static struct Border STD_FileBox = {
  292.     0, 0, FP, BP, JAM1, NVEC, Vectors, NULL
  293. };
  294.  
  295. static struct IntuiText STD_Text[3] = {
  296.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Directory:", NULL },
  297.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"File Name:", NULL },
  298.     { FP, BP, JAM2, 0, 0, NULL, (UBYTE *)"Pattern:", NULL }
  299. };
  300.  
  301. static
  302. OpenFileWindow()
  303. {
  304.     extern struct IntuitionBase *IntuitionBase;
  305.     int i;
  306.  
  307.     /* Rebuild gadget list */
  308.  
  309.     STD_NewWindow.FirstGadget = &STD_Gadget[0];
  310.     for(i = 0; i < GADGETS; i++)
  311.     STD_Gadget[i].NextGadget = (i==GADGETS-1)?(0):(&STD_Gadget[i+1]);
  312.     for(i = 0; i < STRINGS; i++) {
  313.     STD_String[i].BufferPos = strlen(SBuffer[i]);
  314.     STD_String[i].DispPos = 0;
  315.     }
  316.     STD_Prop.VertBody = 0xFFFF;
  317.     STD_Prop.VertPot = 0;
  318.  
  319.     if (!(STD_Window = OpenWindow(&STD_NewWindow)))
  320.     return(0);
  321.  
  322.     /* This optional line will activate a string gadget     */
  323.     if (IntuitionBase->LibNode.lib_Version > 32)
  324.     ActivateGadget(G(1),STD_Window,0L);
  325.     CalcPropGadget();
  326.     PaintFileWindow();
  327.     return (1);
  328. }
  329.  
  330. static
  331. CloseFileWindow()
  332. {
  333.     STD_NewWindow.LeftEdge = STD_Window->LeftEdge;
  334.     STD_NewWindow.TopEdge = STD_Window->TopEdge;
  335.     if (STD_Window)
  336.     CloseWindow(STD_Window);
  337. }
  338.  
  339. static int State;
  340.  
  341. #define INITIAL 0
  342. #define DIRECTORY 1
  343.  
  344. static
  345. PaintFileWindow()
  346. {
  347.     DrawBorder(STD_Window->RPort, &STD_FileBox, 0, 0);
  348.     PrintIText(STD_Window->RPort, &STD_Text[0], LEFTMAR, TP1);
  349.     PrintIText(STD_Window->RPort, &STD_Text[1], LEFTMAR, TP2);
  350.     PrintIText(STD_Window->RPort, &STD_Text[2], LEFTMAR, TP3);
  351.     if (State == DIRECTORY)
  352.     PrintFileNames();
  353. }
  354.  
  355. static int FirstFile;
  356. static int Selected;
  357. static int NumFiles;
  358.  
  359. static struct dirent {
  360.     struct dirent *nextfile;
  361.     SHORT filetype;
  362.     char *filename;
  363. } *NameList, **NameTable;
  364.  
  365. #define FILETYPE 0
  366. #define DIRTYPE 1
  367. #define VOLTYPE 2
  368.  
  369. static
  370. PrintFileNames()
  371. {
  372.     int i;
  373.  
  374.     for (i = 0; i < MAXFILES; ++i) {
  375.     SetBPen(STD_Window->RPort, BP);
  376.     SetAPen(STD_Window->RPort, BP);
  377.     RectFill(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ,
  378.          LASTX, HOMEY+(i+1)*CHSIZ);
  379.     if (i+FirstFile < NumFiles)
  380.         PrintName(i+FirstFile, i+FirstFile == Selected);
  381.     }
  382. }
  383.  
  384. static
  385. PrintName(file, hilite)
  386. int file;
  387. int hilite;
  388. {
  389.     int i;
  390.  
  391.     i = file - FirstFile;
  392.  
  393.     Move(STD_Window->RPort, HOMEX, HOMEY+i*CHSIZ+BASELINE);
  394.     if (hilite == 0) {
  395.     SetBPen(STD_Window->RPort, BP);
  396.     if(NameTable[file]->filetype == FILETYPE)
  397.         SetAPen(STD_Window->RPort, FP);
  398.     else
  399.         SetAPen(STD_Window->RPort, 3);
  400.     } else {
  401.     SetAPen(STD_Window->RPort, BP);
  402.     if(NameTable[file]->filetype == FILETYPE)
  403.         SetBPen(STD_Window->RPort, FP);
  404.     else
  405.         SetBPen(STD_Window->RPort, 3);
  406.     }
  407.     Text(STD_Window->RPort, NameTable[file]->filename,
  408.      strlen(NameTable[file]->filename));
  409. }
  410.  
  411. static
  412. void
  413. CalcPropGadget()
  414. {
  415.     int VertPot, VertBody;
  416.  
  417.     if (State == INITIAL)
  418.     return;
  419.     if (NumFiles <= MAXFILES) {
  420.     VertBody = 0xFFFF;
  421.     VertPot = 0;
  422.     FirstFile = 0;
  423.     } else {
  424.     VertBody = ((MAXFILES<<16)-1) / NumFiles;
  425.     VertPot = 0;
  426.     FirstFile = 0;
  427.     }
  428.     ModifyProp(&STD_Gadget[BARID], STD_Window, NULL,
  429.     STD_Prop.Flags, 0, VertPot, 0, VertBody
  430.     );
  431. }
  432.  
  433. static
  434. void
  435. CalcFilePosition()
  436. {
  437.     short old_pos;
  438.  
  439.     if (State == INITIAL)
  440.      return;
  441.     old_pos = FirstFile;
  442.     if (NumFiles<=MAXFILES) {
  443.     FirstFile = 0;
  444.     } else {
  445.     int VertPot = STD_Prop.VertPot;
  446.     FirstFile = ((VertPot+1)*(NumFiles-MAXFILES))>>16;
  447.     }
  448.     if (old_pos != FirstFile)
  449.     PrintFileNames();
  450. }
  451.  
  452. FreeList(list)
  453. struct dirent *list;
  454. {
  455.     struct dirent *ptr;
  456.  
  457.     while(list) {
  458.     ptr = list->nextfile;
  459.     if (list->filename)
  460.         free(list->filename);
  461.     free(list);
  462.     list = ptr;
  463.     }
  464. }
  465.  
  466. static
  467. ReadNewDir()
  468. {
  469.     struct dirent *NewList, **NewTable, *ptr;
  470.     int NewCount;
  471.     FIB *fib;
  472.     BPTR dirlock;
  473.  
  474.     if (State != DIRECTORY) {
  475.     NameTable = 0;
  476.     NameList = 0;
  477.     }
  478.     if (DirName[0]) {
  479.         dirlock = Lock(DirName, ACCESS_READ);
  480.     } else {
  481.     BPTR ram;
  482.     if (ram = Lock("RAM:", ACCESS_READ)) {
  483.         dirlock = CurrentDir(ram);
  484.         CurrentDir(dirlock);
  485.         dirlock = DupLock(dirlock); /*  added */
  486.         UnLock(ram);
  487.     }
  488.     }
  489.     if (!dirlock)
  490.     return(0);
  491.     if ((fib = (FIB *)malloc(sizeof(FIB))) == NULL) {
  492.     UnLock(dirlock);
  493.     return 0;
  494.     }
  495.     if (!Examine(dirlock, fib)) {
  496.     UnLock(dirlock);
  497.     free(fib);
  498.     return 0;
  499.     }
  500.     if (fib->fib_DirEntryType < 0) {
  501.     UnLock(dirlock);
  502.     free(fib);
  503.     return 0;
  504.     }
  505.     NewList = 0;
  506.     NewCount = 0;
  507.     while(ExNext(dirlock, fib)) {
  508.     NewCount += 1;
  509.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  510.     if (ptr == 0) {
  511.         FreeList(NewList);
  512.         UnLock(dirlock);
  513.         free(fib);
  514.         return(0);
  515.     }
  516.     ptr->nextfile = NewList;
  517.     ptr->filetype = (fib->fib_DirEntryType<0)?FILETYPE:DIRTYPE;
  518.     ptr->filename = malloc(strlen(fib->fib_FileName)+1);
  519.     if (ptr->filename == 0) {
  520.         FreeList(ptr);
  521.         UnLock(dirlock);
  522.         free(fib);
  523.         return(0);
  524.     }
  525.     strcpy(ptr->filename, fib->fib_FileName);
  526.     NewList = ptr;
  527.     }
  528.     free(fib);
  529.     if (DirName[0])
  530.     UnLock(dirlock);
  531.     NewTable = malloc(sizeof(struct dirent *) * NewCount);
  532.     if (NewTable==0) {
  533.     FreeList(NewList);
  534.     return(0);
  535.     }
  536.     FreeList(NameList);
  537.     NameList = NewList;
  538.     if (NameTable)
  539.     free(NameTable);
  540.     NameTable = NewTable;
  541.     if (PatName[0]==0)
  542.     SetPatName("*");
  543.     State = DIRECTORY;
  544.     Selected = -1;
  545.     ReCalcPattern();
  546. }
  547.  
  548.  
  549. static
  550. ReadVol()
  551. {
  552.     struct dirent *NewList, **NewTable, *ptr;
  553.     int NewCount;
  554.     char name[MAXNAME];
  555.  
  556.     if (State != DIRECTORY) {
  557.     NameTable = 0;
  558.     NameList = 0;
  559.     }
  560.     OpenVolList();
  561.     NewList = 0;
  562.     NewCount = 0;
  563.     while(ReadVolList(name)) {
  564.     NewCount += 1;
  565.     ptr = (struct dirent *)malloc(sizeof(struct dirent));
  566.     if (ptr==0) {
  567.         FreeList(NewList);
  568.         return(0);
  569.     }
  570.     ptr->nextfile = NewList;
  571.     ptr->filetype = VOLTYPE;
  572.     ptr->filename = malloc(strlen(name)+1);
  573.     if (ptr->filename == 0) {
  574.         FreeList(ptr);
  575.         return(0);
  576.     }
  577.     strcpy(ptr->filename, name);
  578.     NewList = ptr;
  579.     }
  580.     CloseVolList();
  581.     NewTable = malloc(sizeof(struct dirent *)*NewCount);
  582.     if (NewTable==0) {
  583.     FreeList(NewList);
  584.     return(0);
  585.     }
  586.     FreeList(NameList);
  587.     NameList = NewList;
  588.     if (NameTable)
  589.     free(NameTable);
  590.     NameTable = NewTable;
  591.  
  592.     if (PatName[0]==0)
  593.     SetPatName("*");
  594.  
  595.     State = DIRECTORY;
  596.     Selected = -1;
  597.  
  598.     ReCalcPattern();
  599. }
  600.  
  601. /* this routine does a true dictionary search:
  602.  *
  603.  *        Devs < devs but Devs > devices
  604.  */
  605.  
  606. static
  607. table_compare(p1, p2)
  608. struct dirent **p1, **p2;
  609. {
  610.     char *s1, *s2;
  611.     char c1, c2;
  612.     char firstdiff;
  613.  
  614.     s1 = (*p1)->filename;
  615.     s2 = (*p2)->filename;
  616.     firstdiff = 0;
  617.  
  618.     while(*s1 && *s2) {
  619.     c1 = *s1++;
  620.     c2 = *s2++;
  621.     if (firstdiff==0)
  622.         firstdiff = c1 - c2;
  623.     if (c1 >= 'A' && c1 <= 'Z') c1 = c1+'@';
  624.     if (c2 >= 'A' && c2 <= 'Z') c2 = c2+'@';
  625.     if (c1 != c2)
  626.         return c1 - c2;
  627.     }
  628.     return firstdiff;
  629. }
  630.  
  631. static
  632. sort_table()
  633. {
  634.     qsort(NameTable, NumFiles, sizeof(struct dirent *), table_compare);
  635.     return 1;
  636. }
  637.  
  638. static
  639. ReCalcPattern()
  640. {
  641.     if (State != DIRECTORY) {
  642.     ReadNewDir();
  643.     } else {
  644.     struct dirent *ptr;
  645.  
  646.     if (!PatName[0])
  647.         SetPatName("*");
  648.     NumFiles = 0;
  649.     for (ptr = NameList; ptr; ptr=ptr->nextfile) {
  650.         /* Directories always match. Is this good? */
  651.         if (ptr->filetype == DIRTYPE || ptr->filetype == VOLTYPE ||
  652.         newwildcmp(PatName, ptr->filename)) {
  653.         NameTable[NumFiles] = ptr;
  654.         NumFiles++;
  655.         }
  656.     }
  657.     sort_table();
  658.     CalcPropGadget();
  659.     Selected = -1;
  660.     PrintFileNames();
  661.     }
  662. }
  663.  
  664. static
  665. SetGadgetText(id, text)
  666. int id;
  667. char *text;
  668. {
  669.     int position;
  670.  
  671.     position = RemoveGadget(STD_Window, G(id));
  672.     if (position != -1) {
  673.     strcpy(SBuffer[id], text);
  674.     STD_String[id].BufferPos = strlen(text);
  675.     position = AddGadget(STD_Window, G(id), -1);
  676.     if (position != -1)
  677.         RefreshGadgets(G(id), STD_Window, NULL);
  678.     }
  679. }
  680.  
  681.  
  682. static
  683. SetDirName(name)
  684. char *name;
  685. {
  686.     char buffer[MAXFULL+1], *ptr;
  687.     int  index;
  688.     char lastchar;
  689.  
  690.     /* Can't enter a file name too long. */
  691.  
  692.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  693.     DisplayBeep();
  694.     return(0);
  695.     }
  696.     index = 0;
  697.     lastchar = 0;
  698.     for (ptr = (char *)DirName; *ptr; ptr++)
  699.     buffer[index++] = lastchar = *ptr;
  700.     if (lastchar != ':' && lastchar != 0)
  701.     buffer[index++] = '/';
  702.     strcpy(&buffer[index], name);
  703.     SetGadgetText(DIRID, buffer);
  704.     SetGadgetText(FILID, "");
  705.     return(1);
  706. }
  707.  
  708. static
  709. SetFileName(name)
  710. char *name;
  711. {
  712.     /* Can't enter a file name too long. */
  713.     if (strlen(DirName) + strlen(name) + 1 > MAXFULL) {
  714.     DisplayBeep();
  715.     return(0);
  716.     }
  717.     SetGadgetText(FILID, name);
  718.     return(1);
  719. }
  720.  
  721. static
  722. SetPatName(name)
  723. char *name;
  724. {
  725.     SetGadgetText(PATID, name);
  726. }
  727.  
  728. static
  729. ProcessGadget(id)
  730. int id;
  731. {
  732.     switch(id) {
  733.     case DIRID: ReadNewDir();       break;
  734.     case FILID: ProcessFileName();  break;
  735.     case PATID: ReCalcPattern();    break;
  736.     case BARID: CalcFilePosition(); break;
  737.     case YESID: DoneFlag = 1;        break;
  738.     case CANID: DoneFlag = -1;        break;
  739.     case VOLID: ReadVol();          break;
  740.     }
  741. }
  742.  
  743. /*
  744.  *  ProcessFileName() added by Matthew Dillon.  If the requested file is
  745.  *  actually a directory, do a ReadNewDir() instead of quiting.
  746.  */
  747.  
  748. void
  749. ProcessFileName()
  750. {
  751.     register char *ptr;
  752.     register short len;
  753.     BPTR fillock;
  754.     char buf[128];
  755.     FIB *fib = (FIB *)malloc(sizeof(FIB));
  756.  
  757.     if (fib == NULL) {
  758.     DoneFlag = 1;
  759.     return;
  760.     }
  761.     for (ptr = (char *)FileName; *ptr; ++ptr) {
  762.     if (*ptr == ':') {
  763.         DirName[0] = '\0';
  764.         break;
  765.     }
  766.     }
  767.     strcpy(buf, DirName);
  768.     if (FileName[0]) {
  769.     if (len = strlen(buf)) {
  770.         if (buf[len-1]!=':')
  771.         strcat(buf, "/");
  772.     }
  773.     strcat(buf, FileName);
  774.     if (fillock = Lock(buf, ACCESS_READ)) {
  775.         if (Examine(fillock, fib)) {
  776.         if (fib->fib_DirEntryType > 0) {
  777.             SetGadgetText(DIRID, buf);
  778.             SetGadgetText(FILID, "");
  779.             ReadNewDir();
  780.             free(fib);
  781.             UnLock(fillock);
  782.             return;
  783.         }
  784.         }
  785.         UnLock(fillock);
  786.     }
  787.     }
  788.     free(fib);
  789.     DoneFlag = 1;
  790. }
  791.  
  792.  
  793. static
  794. ProcessMouse(x, y, code, seconds, micros)
  795. {
  796.     int NewSelected;
  797.     static int oseconds = 0, omicros = 0;
  798.  
  799.     if (x < HOMEX || y < HOMEY || x >= LASTX || y >= LASTY)
  800.     return;
  801.     if ((code & SELECTUP) == SELECTUP)
  802.     return;
  803.     if (State != DIRECTORY) {
  804.     ReadNewDir();
  805.     return;
  806.     }
  807.     NewSelected = (y-HOMEY)/CHSIZ + FirstFile;
  808.     if (NewSelected == Selected) {
  809.     if (Selected != -1) {
  810.         if (DoubleClick(oseconds, omicros, seconds, micros)) {
  811.         if (NameTable[Selected]->filetype == DIRTYPE) {
  812.             if (SetDirName(NameTable[Selected]->filename))
  813.             ReadNewDir();
  814.         } else if (NameTable[Selected]->filetype == VOLTYPE) {
  815.             SetGadgetText(DIRID, NameTable[Selected]->filename);
  816.             SetGadgetText(FILID, "");
  817.             ReadNewDir();
  818.         } else if (!SetFileName(NameTable[Selected]->filename)) {
  819.             Selected = -1;
  820.             DoneFlag = 1;
  821.         }
  822.         }
  823.     }
  824.     } else {
  825.     if (Selected != -1 && Selected >= FirstFile &&
  826.         Selected < FirstFile+MAXFILES)
  827.         PrintName(Selected, 0);
  828.     Selected = NewSelected;
  829.     if (Selected >= NumFiles) {
  830.         Selected = -1;
  831.     } else {
  832.         if (SetFileName(NameTable[Selected]->filename))
  833.         PrintName(Selected, 1);
  834.         else
  835.         Selected = -1;
  836.         if (IntuitionBase->LibNode.lib_Version > 32)
  837.         ActivateGadget(G(1),STD_Window,0L);
  838.     }
  839.     }
  840.     oseconds = seconds;
  841.     omicros = micros;
  842. }
  843.  
  844. stdfile(title, deffile, defpat, name)
  845. char *title, *deffile, *defpat, *name;
  846. {
  847.     IMESS *im;
  848.  
  849.     if(title)
  850.     STD_NewWindow.Title = (UBYTE *)title;
  851.     else
  852.     STD_NewWindow.Title = (UBYTE *)"Enter File Name";
  853.     if (deffile) {
  854.     int i;
  855.     for (i = strlen(deffile)-1; i >= 0; --i) {
  856.         if (deffile[i]==':' || deffile[i]=='/') {
  857.         int hold;
  858.         strcpy(FileName, &deffile[i+1]);
  859.         if (deffile[i]==':')
  860.             i++;
  861.         hold = deffile[i];
  862.         deffile[i] = 0;
  863.         strcpy(DirName, deffile);
  864.         deffile[i] = hold;
  865.         break;
  866.         }
  867.     }
  868.     if (i < 0) {
  869.         strcpy(FileName, deffile);
  870.         DirName[0] = 0;
  871.     }
  872.     } else {
  873.     DirName[0] = 0;
  874.     FileName[0] = 0;
  875.     }
  876.     if (defpat)
  877.     strcpy(PatName, defpat);
  878.     else
  879.     PatName[0] = 0;
  880.  
  881.     State = INITIAL;
  882.     NameTable = 0;
  883.     NameList = 0;
  884.  
  885.     if(!OpenFileWindow())
  886.     return(0);
  887.     DoneFlag = 0;
  888.     while (!DoneFlag) {
  889.     Wait(1<<STD_Window->UserPort->mp_SigBit);
  890.     while(im = GetMsg(STD_Window->UserPort)) {
  891.         switch(im->Class) {
  892.         case CLOSEWINDOW:
  893.         DoneFlag = -1;
  894.         break;
  895.         case MOUSEBUTTONS:
  896.         ProcessMouse(im->MouseX, im->MouseY, im->Code, im->Seconds,
  897.                  im->Micros);
  898.         break;
  899.         case GADGETUP:
  900.         ProcessGadget(((struct Gadget *)im->IAddress)->GadgetID);
  901.         break;
  902.         case REFRESHWINDOW:
  903.         BeginRefresh(STD_Window);
  904.         PaintFileWindow();
  905.         EndRefresh(STD_Window, 1);
  906.         break;
  907.         }
  908.         ReplyMsg(im);
  909.     }
  910.     }
  911.     CloseFileWindow();
  912.     FreeList(NameList);
  913.  
  914.     if (NameTable)
  915.     free(NameTable);
  916.     if (DoneFlag == 1) {
  917.     int len;
  918.  
  919.     strcpy(name, DirName);
  920.     if (FileName[0]) {
  921.         if (len = strlen(name)) {
  922.         if (name[len-1]!=':')
  923.             strcat(name, "/");
  924.         }
  925.         strcat(name, FileName);
  926.         return(1);
  927.     }
  928.     }
  929.     return(0);
  930. }
  931.  
  932. /*
  933.  *  VOLLIST.C
  934.  */
  935.  
  936. #define toAPTR(b) ((b)<<2)
  937. #define toBPTR(a) ((a)>>2)
  938.  
  939. struct DeviceList *list;
  940.  
  941. OpenVolList()
  942. {
  943.     extern DOSLIB *DOSBase;
  944.     ROOTNODE *root;
  945.     DOSINFO  *info;
  946.  
  947.     root =   (ROOTNODE *)DOSBase->dl_Root;
  948.     info =   (DOSINFO  *)toAPTR(root->rn_Info);
  949.     list = (DEVLIST *)toAPTR(info->di_DevInfo);
  950. }
  951.  
  952. ReadVolList(name)
  953. char *name;
  954. {
  955.     register DEVLIST *next;
  956.  
  957.     while(list) {
  958.     next = (DEVLIST *)toAPTR(list->dl_Next);
  959.     if (list->dl_Type == DLT_VOLUME) {
  960.         char *ptr;
  961.         int count;
  962.         ptr = (char *)toAPTR((BPTR)list->dl_Name);
  963.         count = *ptr++;
  964.         if (count > 30)
  965.         count = 30;
  966.         strncpy(name, ptr, count);
  967.         name[count++] = ':';
  968.         name[count] = 0;
  969.         list = next;
  970.         return(1);
  971.     }
  972.     list = next;
  973.     }
  974.     return(0);
  975. }
  976.  
  977. CloseVolList()
  978. {
  979. }
  980.  
  981.  
  982.